﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace ELearning.Wpf.UI
{
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;

    using ELearning.Data.LearningDatasetTableAdapters;

    /// <summary>
    /// Interaction logic for wndCreateTest.xaml
    /// </summary>
    public partial class wndCreateTest : Window
    {
        private readonly long _subjectId;

        private Test _currentTest;
        private long _currentTestId;

        private Question _currentQuestion;

        //for testing purposes
        public wndCreateTest()
            : this(3)
        {
        }

        public wndCreateTest(long subjectId)
        {
            _subjectId = subjectId;
            InitializeComponent();
            _currentTest = new Test();
            _currentTest.Name = "Новий тест";
            _currentTest.Questions = new List<Question>();
            AddQuestionAndSetAsCurrent();
            btDeleteTest.Visibility = Visibility.Hidden;
            Rebind();
        }

        public wndCreateTest(long subjectId, long testId)
        {
            _subjectId = subjectId;
            _currentTestId = testId;
            InitializeComponent();
            btDeleteTest.Visibility = Visibility.Visible;

            using (TestsTableAdapter tableAdapter = new TestsTableAdapter())
            {
                var table = tableAdapter.GetDataByID(testId);
                if (table.Count <= 0)
                {
                    string message = string.Format("Test with id={0} not found in database!", testId);
                    DebugHelper.ShowDebugMessageBox(message);
                    throw new Exception(message);
                }

                var testRow = table[0];
                var test = LoadTestFromByteArray(testRow.BinaryData);
                _currentTest = test;
                if (_currentTest.Questions == null)
                {
                    _currentTest.Questions = new List<Question>();
                }

                if (_currentTest.Questions.Count <= 0)
                {
                    AddQuestionAndSetAsCurrent();
                }
                else
                {
                    _currentQuestion = _currentTest.Questions[0];
                }
            }

            tbTestName.Text = _currentTest.Name;
            Rebind();
        }

        public static Test LoadTestFromByteArray(byte[] binaryData)
        {
            using (Stream ms = new MemoryStream(binaryData))
            {
                BinaryFormatter bf = new BinaryFormatter();
                var test = bf.Deserialize(ms) as Test;
                if (test == null)
                {
                    string message = "Cannot deserialise test from binary data";
                    DebugHelper.ShowDebugMessageBox(message);
                    throw new Exception(message);
                }

                return test;
            }
        }

        private void RemoveItemClick(object sender, RoutedEventArgs e)
        {
            _currentQuestion.Answers.Remove((Answer)((Button)sender).Tag);
            Rebind();
        }

        private void tbQuestionText_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (_currentQuestion == null)
            {
                return;
            }
        
            _currentQuestion.QuestionText = tbQuestionText.Text;
        }

        private void btAddAnswer_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(tbNewAnswerText.Text))
            {
                return;
            }

            _currentQuestion.Answers.Add(new Answer { Text = tbNewAnswerText.Text });
            tbNewAnswerText.Text = string.Empty;

            Rebind();
            tbNewAnswerText.Focus();
        }

        private void Rebind()
        {
            lbAnswers.DataContext = null;
            if (_currentQuestion.Answers == null)
            {
                _currentQuestion.Answers  = new List<Answer>();
            }

            lbAnswers.DataContext = _currentQuestion.Answers;
            tbQuestionText.Text = _currentQuestion.QuestionText;
            RefreshCounter();
        }

        private void btAddQuestion_Click(object sender, RoutedEventArgs e)
        {
            AddQuestionAndSetAsCurrent();
            Rebind();
        }

        private void AddQuestionAndSetAsCurrent()
        {
            _currentQuestion = new Question();
            _currentQuestion.Answers = new List<Answer>();
            _currentTest.Questions.Add(_currentQuestion);
        }

        private void RefreshCounter()
        {
            lbCounter.Content = string.Format("{0}/{1}", GetCurrentQuestionIndex() + 1, _currentTest.Questions.Count);
        }

        private int GetCurrentQuestionIndex()
        {
            return _currentTest.Questions.IndexOf(_currentQuestion);
        }

        private void btPrevQuestion_Click(object sender, RoutedEventArgs e)
        {
            int questionIndex = GetCurrentQuestionIndex();
            int newQuestionIndex;
            if (questionIndex == 0)
            {
                newQuestionIndex = _currentTest.Questions.Count - 1;
            }
            else
            {
                newQuestionIndex = questionIndex - 1;
            }

            if (questionIndex == newQuestionIndex)
            {
                return;
            }

            _currentQuestion = _currentTest.Questions[newQuestionIndex];
            Rebind();
        }

        private void btNextQuestion_Click(object sender, RoutedEventArgs e)
        {
            int questionIndex = GetCurrentQuestionIndex();
            int newQuestionIndex;

            if (questionIndex + 1 >= _currentTest.Questions.Count)
            {
                newQuestionIndex = 0;
            }
            else
            {
                newQuestionIndex = questionIndex + 1;
            }

            _currentQuestion = _currentTest.Questions[newQuestionIndex];
            Rebind();
        }

        private void btSave_Click(object sender, RoutedEventArgs e)
        {
            _currentTest.Name = tbTestName.Text;
            using (TestsTableAdapter tableAdapter = new TestsTableAdapter())
            using(MemoryStream ms = new MemoryStream())
            {

                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(ms, _currentTest);
                var bytes = ms.GetBuffer();
                tableAdapter.Insert(_subjectId, _currentTest.Name, bytes);
            }

            DialogResult = true;
            Close();
        }

        private void btDeleteTest_Click(object sender, RoutedEventArgs e)
        {
            using (TestsTableAdapter tableAdapter = new TestsTableAdapter())
            {
                tableAdapter.Delete(_currentTestId);
            }

            DialogResult = true;
            Close();
        }
    }
}
